package tr.gov.tubitak.bilgem.esya.android.signexample;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import javax.smartcardio.CardTerminal;

import tr.gov.tubitak.uekae.esya.api.asn.x509.ECertificate;
import tr.gov.tubitak.uekae.esya.api.cmssignature.ISignable;
import tr.gov.tubitak.uekae.esya.api.cmssignature.SignableByteArray;
import tr.gov.tubitak.uekae.esya.api.cmssignature.SignableFile;
import tr.gov.tubitak.uekae.esya.api.cmssignature.attribute.EParameters;
import tr.gov.tubitak.uekae.esya.api.cmssignature.attribute.IAttribute;
import tr.gov.tubitak.uekae.esya.api.cmssignature.attribute.SigningTimeAttr;
import tr.gov.tubitak.uekae.esya.api.cmssignature.signature.BaseSignedData;
import tr.gov.tubitak.uekae.esya.api.cmssignature.signature.ESignatureType;
import tr.gov.tubitak.uekae.esya.api.common.bundle.I18nSettings;
import tr.gov.tubitak.uekae.esya.api.common.crypto.Algorithms;
import tr.gov.tubitak.uekae.esya.api.common.crypto.BaseSigner;
import tr.gov.tubitak.uekae.esya.api.common.util.Base64;
import tr.gov.tubitak.uekae.esya.api.common.util.LicenseUtil;
import tr.gov.tubitak.uekae.esya.api.common.util.StringUtil;
import tr.gov.tubitak.uekae.esya.api.smartcard.android.ccid.reader.SCDTerminalHandler;
import tr.gov.tubitak.uekae.esya.api.smartcard.apdu.APDUSmartCard;
import tr.gov.tubitak.uekae.esya.api.smartcard.apdu.TerminalHandler;
import tr.gov.tubitak.uekae.esya.asn.util.AsnIO;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {

    //private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
    private static final String TAG ="MainActivity";

    TerminalHandler mTerminalHandler ;
    APDUSmartCard mAPDUSmartCard;

    private class LoadCertificatesTask extends AsyncTask<CardTerminal, Void, Exception> {
        private ProgressDialog progress;
        public LoadCertificatesTask(Activity callerActivity){
            this.callerActivity = callerActivity;
        }

        Activity callerActivity;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progress = new ProgressDialog(MainActivity.this);
            progress.setMessage("Sertifikalar yükleniyyor.\n Lütfen bekleyin...");
            progress.show();
        }

        @Override
        protected Exception doInBackground(CardTerminal... params) {
            Exception result = null;
            PendingIntent permissionIntent = PendingIntent.getBroadcast(callerActivity, 0, new Intent("tr.gov.tubitak.bilgem.esya.android.signexample.USB_PERMISSION"), 0);
            SCDTerminalHandler terminalHandler = new SCDTerminalHandler(callerActivity,permissionIntent);
            try {
                mAPDUSmartCard = new APDUSmartCard(terminalHandler);
                mAPDUSmartCard.setDisableSecureMessaging(true);

                CardTerminal[] terminalList = mAPDUSmartCard.getTerminalList();
                if(terminalList.length == 0)
                {
                    showMessage("Hata","Bağlı terminal sayısı 0");
                    return null;
                }
                CardTerminal cardTerminal = terminalList[0];
                mAPDUSmartCard.openSession(cardTerminal);
                String readerName = cardTerminal.getName();
                List<byte[]> signCertValueList = mAPDUSmartCard.getSignatureCertificates();
                for(byte[] signCertValue:signCertValueList)
                {
                    ECertificate signCert = new ECertificate(signCertValue);
                    //Sadece nitelikli sertifikalar çekiliyor.
                    //Kanuni geçerliliği olmayan sertifikalarla imza atılmak istenirse bu kontrol kaldırılabilir.
                    //  if(signCert.isQualifiedCertificate()){
                    certListAdapter.addItem(cardTerminal,signCert);
                    Log.d(TAG, "Sertifika Sahibi :"+signCert.getSubject().getCommonNameAttribute());
                    //}
                }
                handler.sendEmptyMessage(1);
                try
                {
                    //Sleep for two seconds
                    Thread.sleep(2000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            } catch (Exception exc) {
                Log.e(TAG,"Sertifikalar alınırken hata oluştu.",exc);
                result = exc;
            }
            return result;
        }

        @Override
        protected void onPostExecute(Exception result) {
            progress.dismiss();
        }
    }

    void showMessage(String title,String message){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(message)
                .setTitle(title);
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    public class SignFileTask  extends
            AsyncTask<Void, Void, Void>
    {
        private ProgressDialog progress;
        Exception exc;
        String destFilePath;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progress = new ProgressDialog(MainActivity.this);
            progress.setMessage("İmzalama işlemi yapılıyor.\n Lütfen Bekleyiniz...");
            progress.show();
        }

        @Override
        protected Void doInBackground(Void... arg0)
        {
            try
            {
                Locale trLocale = new Locale("tr","TR");
                Locale.setDefault(trLocale);
                I18nSettings.setLocale(trLocale);
                EditText pwdEdit = (EditText)findViewById(R.id.editPassword);
                String pwdText = pwdEdit.getText().toString();
                if(pwdText.isEmpty()){
                    exc = new Exception("Parola girilmedi.");
                    return null;
                }

                String sourceFilePath = filePathView.getText().toString();
                if(sourceFilePath.isEmpty()){
                    exc = new Exception("Dosya Seçilmedi.");
                    return null;
                }
                mAPDUSmartCard.login(pwdText);
                Pair<CardTerminal,ECertificate> selection = certListAdapter.getSelection();
                ECertificate signCert = selection.second;
                BaseSigner signer = mAPDUSmartCard.getSigner(signCert.asX509Certificate(), Algorithms.SIGNATURE_RSA_SHA1);
                BaseSignedData bsd = new BaseSignedData();

                ISignable content = new SignableFile(new File(sourceFilePath));
                bsd.addContent(content);
                //Since SigningTime attribute is optional,add it to optional attributes list
                List<IAttribute> optionalAttributes = new ArrayList<IAttribute>();
                optionalAttributes.add(new SigningTimeAttr(Calendar.getInstance()));
                HashMap<String, Object> params = new HashMap<String, Object>();

                params.put(EParameters.P_VALIDATE_CERTIFICATE_BEFORE_SIGNING,false);
                bsd.addSigner(ESignatureType.TYPE_BES, signCert, signer, optionalAttributes, params);
                byte [] signedDocument = bsd.getEncoded();
                System.out.println("İmzalama işlemi tamamlandı. Dosyaya yazılacak. Imzali Veri ="+StringUtil.toString(signedDocument));
                destFilePath = sourceFilePath+ ".imz";
                //destFilePath = "/sdcard/sdcard0/SignedDoc.imz";
                AsnIO.dosyayaz(signedDocument, destFilePath);
            }
            catch(Exception ex)
            {
                exc = ex;
                ex.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            progress.dismiss();
            if(exc!=null){
                showMessage("Hata Oluştu","İmzalama işlemi sırasında hata oluştu."+exc.getLocalizedMessage());
            }
            else
            {
                showMessage("İşlem Tamamlandı.",destFilePath+" konumunda imzalı dosya oluşturuldu.");
            }
        }
    }

    private Handler handler = new Handler()
    {

        @Override
        public void handleMessage(Message msg)
        {
            certListAdapter.notifyDataSetChanged();
            super.handleMessage(msg);
        }

    };

    void loadCertTree(){
        LoadCertificatesTask loadCertificatesTask = new LoadCertificatesTask(this);
        loadCertificatesTask.execute();
    }

    CertListAdapter certListAdapter;
    ListView certTreeList;
    void initCertTreeView(){
        // Retrive the ExpandableListView from the layout
        certTreeList = (ListView) findViewById(R.id.certListView);
        certTreeList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

        certListAdapter = new CertListAdapter(this);
        certTreeList.setAdapter(certListAdapter);
    }

    private static final int REQUEST_PICK_FILE = 1;

    TextView filePathView;


    @Override
    protected void onDestroy() {
        if(mAPDUSmartCard!=null){
            try
            {
                mAPDUSmartCard.logout();
            }
            catch(Exception exc)
            {
            }

            try
            {
                mAPDUSmartCard.closeSession();
            }
            catch(Exception exc)
            {
                exc.printStackTrace();
            }
        }
        super.onDestroy();
    }

    public void loadLicense()
    {
        try {
            //Load license
            Resources res = getResources();
            InputStream lisansStream = res.openRawResource(R.raw.lisans_test);
            LicenseUtil.setLicenseXml(lisansStream);
            lisansStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        loadLicense();
        initCertTreeView();

        ///
        /*
        UsbManager usbManager = (UsbManager)getSystemService("usb");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent("com.infothink.smartcard.USB_PERMISSION"),0);
        USBReader usbReader = new USBReader(pendingIntent,usbManager);
        try {
			usbReader.Open();
			//int getSlotStatus = usbReader.GetSlotStatus();
			usbReader.WaitCardEvent(USBReader.CARD_EVENT_DETECED);
			TestCard card = (TestCard) usbReader.ConnectCard("com.scdroid.TestCard", Card.PROTOCOL_ANY);
			byte[] getParameters = usbReader.GetParameters();			
			int a=5;
		} catch (SCException e) {
			e.printStackTrace();
		}*/

        ///

        loadCertTree();
        //signWithFirstCertificate();
        Button btn = (Button) findViewById(R.id.btn_Sign);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new SignFileTask().execute();
            }
        });

        filePathView = (TextView) findViewById(R.id.txtFilePath);

        Button btnSelectFile = (Button) findViewById(R.id.btn_SelectFile);
        btnSelectFile.requestFocus();
        btnSelectFile.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,FilePickerActivity.class);
                startActivityForResult(intent, REQUEST_PICK_FILE);
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(resultCode == RESULT_OK) {
            switch(requestCode) {
                case REQUEST_PICK_FILE:
                    if(data.hasExtra(FilePickerActivity.EXTRA_FILE_PATH)) {
                        // Get the file path
                        File f = new File(data.getStringExtra(FilePickerActivity.EXTRA_FILE_PATH));

                        // Set the file path text view
                        filePathView.setText(f.getPath());
                    }
            }
        }
        super.onActivityResult(requestCode, resultCode, data);    //To change body of overridden methods use File | Settings | File Templates.
    }
    
    /*
    public void signWithFirstCertificate()
    {	
        try {
        	//Burada gömülü lisans dosyası yüklenmektedir.    	
            Resources res = getResources();
            InputStream lisansStream = res.openRawResource(R.raw.lisans_test);
            LicenseUtil.setLicenseXml(lisansStream);
            lisansStream.close();            
            Activity callerActivity = this;    
            //SCDTerminalHandler oluşturulurken bunu çağıran Activity parametre olarak verilmelidir.
        	//Kullanıcıdan usb erişim onayı alınabilmesi için oluşturulmuş olan PendingIntent nesnesi terminal handler sınıfına verilmelidir.
            PendingIntent permissionIntent = PendingIntent.getBroadcast(callerActivity, 0, new Intent("tr.gov.tubitak.bilgem.esya.android.signexample.USB_PERMISSION"), 0);            
            SCDTerminalHandler terminalHandler = new SCDTerminalHandler(callerActivity,permissionIntent);
        	//APDUSmartCard sınıfı uygun TerminalHandler sınıfı ile çağrılmalıdır.
        	APDUSmartCard apduSmartCard = new APDUSmartCard(terminalHandler); 
            //Akis kart iletişimi için SecureMessaging devre dışı bırakılmalıdır.
        	apduSmartCard.setDisableSecureMessaging(true);            
            //Bağlı kart okuyucular okunuyor.
            CardTerminal[] terminalList = apduSmartCard.getTerminalList();
            if(terminalList == null || terminalList.length == 0)
            {
            	throw new Exception("Bağlı kart okuyucu sayısı 0");            
            }
            CardTerminal cardTerminal = terminalList[0];
            apduSmartCard.openSession(cardTerminal);            
            //İlk kart okuyucudan sertifika listesi alınıyor.
            List<byte[]> signCertValueList = apduSmartCard.getSignatureCertificates();
            if(signCertValueList == null || signCertValueList.size() == 0)
            {
            	throw new Exception("Kart içerisinde sertifika sayısı 0");            
            }
            //İlk sertifika ile işlem yapılacak.
           ECertificate signingCert = new ECertificate(signCertValueList.get(0));
           String cardPin = "975998";
           apduSmartCard.login(cardPin);     
           //İmzalamada kullanılacak BaseSigner APDUSmartCard2 sınıfından alınıyor.           
           BaseSigner signer = apduSmartCard.getSigner(signingCert.asX509Certificate(), Algorithms.SIGNATURE_RSA_SHA1);
           BaseSignedData bsd = new BaseSignedData();
           
           //Dosya imzalanmak istenirse
           //İmzalanacak olan dosya yolu
           //String sourceFilePath = "/tmp/TextForSign.txt";
           //ISignable content = new SignableFile(new File(sourceFilePath));
           
           //Veri imzalanacak.
           ISignable content = new SignableByteArray("ImzalanacakVeri".getBytes());
           bsd.addContent(content);
           //Since SigningTime attribute is optional,add it to optional attributes list
           List<IAttribute> optionalAttributes = new ArrayList<IAttribute>();
           optionalAttributes.add(new SigningTimeAttr(Calendar.getInstance()));
           HashMap<String, Object> params = new HashMap<String, Object>();
           //Android ile imza atılırken sertifika kontrolü devre dışı bırakılmalıdır.
           //Mevcut sürümde sertifika doğrulama desteği bulunmamaktadır.
           params.put(EParameters.P_VALIDATE_CERTIFICATE_BEFORE_SIGNING,false);
           bsd.addSigner(ESignatureType.TYPE_BES, signingCert, signer, optionalAttributes, params);
           byte [] signedData = bsd.getEncoded();
           System.out.println("******** İmzalı Veri *********");
           System.out.println(Base64.encode(signedData));
           System.out.println("******************************");
           
           // Eğer imzalı hali dosyaya yazılmak istenirse
           //String destFilePath = sourceFilePath+ ".imz";
           //İmzalı hali dosyaya yazılıyor.
           //AsnIO.dosyayaz(signedData, destFilePath);           
           apduSmartCard.logout();
           apduSmartCard.closeSession();						
        }
        catch (Exception e) {
			e.printStackTrace();
		}
    }*/
}
